#include "base_yaml.h"
#include <fstream>
#include <sstream>
#include <algorithm>
#include <cctype>

namespace {

// 辅助函数：去除首尾空白字符
std::string Trim(const std::string &str)
{
    size_t first = str.find_first_not_of(" \t\r\n");
    if (first == std::string::npos)
        return "";
    size_t last = str.find_last_not_of(" \t\r\n");
    return str.substr(first, last - first + 1);
}

// 辅助函数：根据字符串创建对应的YamlValue
El::Base::YamlValue ParseScalar(const std::string &text)
{
    if (text.empty())
        return El::Base::YamlValue(std::map<std::string, El::Base::YamlValue>());
    if (text == "true")
        return El::Base::YamlValue(true);
    if (text == "false")
        return El::Base::YamlValue(false);

    try {
        size_t pos = 0;
        int intVal = std::stoi(text, &pos);
        if (pos == text.size())
            return El::Base::YamlValue(intVal);
    } catch (...) {
        // 忽略异常
    }
    try {
        size_t pos = 0;
        double doubleVal = std::stod(text, &pos);
        if (pos == text.size())
            return El::Base::YamlValue(doubleVal);
    } catch (...) {
        // 忽略异常
    }
    return El::Base::YamlValue(text);
}

} // anonymous namespace

namespace El {
namespace Base {

bool YamlParser::LoadFromFile(const std::string &filename)
{
    std::ifstream file(filename);
    if (!file.is_open()) {
        lastError_ = "无法打开文件: " + filename;
        return false;
    }

    std::stringstream buffer;
    buffer << file.rdbuf();
    return LoadFromString(buffer.str());
}

bool YamlParser::LoadFromString(const std::string &content)
{
    return Parse(content);
}

bool YamlParser::Parse(const std::string &content)
{
    std::istringstream stream(content);
    std::string line;
    std::vector<std::pair<int, YamlValue>> stack;
    std::vector<YamlValue> currentArray;
    std::string lastKey;
    int lastIndent = -1;
    bool inArray = false;

    // 初始化根节点为空map
    root_ = YamlValue(std::map<std::string, YamlValue>());

    // lambda：刷新当前未处理的数组到父映射中
    auto flushCurrentArray = [&]() {
        if (!currentArray.empty()) {
            if (!stack.empty()) {
                auto &parentMap = const_cast<std::map<std::string, YamlValue> &>(stack.back().second.AsMap());
                parentMap[lastKey] = YamlValue(currentArray);
            } else {
                auto &rootMap = const_cast<std::map<std::string, YamlValue> &>(root_.AsMap());
                rootMap[lastKey] = YamlValue(currentArray);
            }
            currentArray.clear();
            inArray = false;
        }
    };

    while (std::getline(stream, line)) {
        line = Trim(line);
        if (line.empty() || line[0] == '#')
            continue;

        int indent = GetIndentation(line);
        line = line.substr(indent);

        // 检查是否是数组项
        bool isArrayItem = false;
        if (!line.empty() && line[0] == '-') {
            isArrayItem = true;
            line = Trim(line.substr(1));
            inArray = true;
        } else if (inArray && indent <= lastIndent) {
            // 结束当前数组
            flushCurrentArray();
        }

        // 处理缩进变化：将栈中indent大于等于当前值的项出栈，并更新父映射
        while (!stack.empty() && stack.back().first >= indent) {
            if (stack.size() >= 2) {
                YamlValue completed = stack.back().second;
                stack.pop_back();
                if (!stack.empty() && stack.back().second.IsMap() && !lastKey.empty()) {
                    auto &parentMap = const_cast<std::map<std::string, YamlValue> &>(stack.back().second.AsMap());
                    parentMap[lastKey] = completed;
                }
            }
            if (!stack.empty())
                stack.pop_back();
        }

        if (isArrayItem) {
            // 使用ParseScalar简化数组项的解析
            YamlValue arrayValue = ParseScalar(line);
            currentArray.push_back(arrayValue);
            lastIndent = indent;
            continue;
        }

        // 处理key-value行，若存在未处理的数组先刷新
        if (!lastKey.empty() && !currentArray.empty()) {
            flushCurrentArray();
        }

        auto [key, value] = SplitKeyValue(line);
        if (!key.empty()) {
            YamlValue yamlValue;
            // 如果value为空，则认为需要创建新的映射，否则解析标量值
            if (value.empty()) {
                yamlValue = YamlValue(std::map<std::string, YamlValue>());
            } else {
                yamlValue = ParseScalar(value);
            }

            if (stack.empty()) {
                auto &rootMap = const_cast<std::map<std::string, YamlValue> &>(root_.AsMap());
                rootMap[key] = yamlValue;
            } else {
                auto &parentMap = const_cast<std::map<std::string, YamlValue> &>(stack.back().second.AsMap());
                parentMap[key] = yamlValue;
            }

            if (value.empty()) {
                stack.push_back({indent, yamlValue});
            }
            lastKey = key;
        }
    }

    // 刷新最后未处理的数组
    if (!currentArray.empty()) {
        if (!stack.empty()) {
            auto &parentMap = const_cast<std::map<std::string, YamlValue> &>(stack.back().second.AsMap());
            parentMap[lastKey] = YamlValue(currentArray);
        } else {
            auto &rootMap = const_cast<std::map<std::string, YamlValue> &>(root_.AsMap());
            rootMap[lastKey] = YamlValue(currentArray);
        }
    }

    return true;
}

int YamlParser::GetIndentation(const std::string &line) const
{
    int spaces = 0;
    while (spaces < static_cast<int>(line.length()) && (line[spaces] == ' ' || line[spaces] == '\t')) {
        spaces += (line[spaces] == '\t') ? 4 : 1;
    }
    return spaces;
}

std::pair<std::string, std::string> YamlParser::SplitKeyValue(const std::string &line) const
{
    size_t pos = line.find(':');
    if (pos == std::string::npos) {
        return {Trim(line), ""};
    }

    std::string key = Trim(line.substr(0, pos));
    std::string value = pos + 1 < line.length() ? Trim(line.substr(pos + 1)) : "";

    return {key, value};
}

YamlValue YamlParser::Get(const std::string &path) const
{
    std::istringstream pathStream(path);
    std::string segment;
    const YamlValue *current = &root_;

    while (std::getline(pathStream, segment, '.')) {
        if (!current->IsMap()) {
            throw std::runtime_error("Invalid path: not a map");
        }

        const auto &map = current->AsMap();
        auto it = map.find(segment);
        if (it == map.end()) {
            throw std::runtime_error("Path not found: " + segment);
        }
        current = &it->second;
    }

    return *current;
}

} // namespace Base
} // namespace El